using System;
using FireStarter.Base;
using Firestarter.DB.Schema.BO;
using Firestarter.DB.Schema.Test.BO.TestUtils;
using FireStarterModeller.BO;
using FireStarterModeller.Test;
using Habanero.Base.Exceptions;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using Habanero.Testability;
using NUnit.Framework;

namespace Firestarter.DB_DomainModel.Logic.Test
{
    public class TestDBToDMClassImporterBase 
    {
        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            ClassDef.ClassDefs.Clear();
            ClassDef.ClassDefs.Add(new XmlClassDefsLoader(BOBroker.GetClassDefsXml(), new DtdLoader()).LoadClassDefs());
        }

        // ReSharper disable RedundantNameQualifier
        [SetUp]
        public void SetupTest()
        {
            GC.Collect();
            GC.WaitForPendingFinalizers();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        // ReSharper restore RedundantNameQualifier

        [TearDown]
        public virtual void TearDownTest()
        {
            //ClassDef.ClassDefs.Clear();
        }
        [Test]
        public void Test_Construct()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Test Result -----------------------
            Assert.IsNotNull(dbToDMClassImporter);
        }

        /// <summary>
        ///-	The user selects to Import Existing Solution from DB
        ///-	If a DB Table is marked as added during the import.
        ///  	- Search for the corresponding DMClass by the MappedTableName,
        ///      - If Found 
        ///         - Update the DMClass with the Mapped TableID.
        ///         - the DMClass is mapped to another Table then do nothing.
        ///         - Update the Properties, relationships etc as per the Table marked as Updated (see below)
        ///      - Else
        ///        -	Create a new DMClass from the DBTable as per requirements above.
        /// </summary>
        [Test]
        public void Test_ExistingMappedTable_FindExistingDMClass()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeUpdated(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            dmClass.MappedDBTable = dbTable;
            //---------------Assert Precondition----------------
            Assert.AreEqual(ChangeType.Update, dbTable.PendingChangeType);
            Assert.IsNotNull(dbTable.GetMappedDMClass());
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
        }
        [Test]
        public void Test_Import_WhenNullDMSolution_ShouldThrowError()
        {
            //---------------Set up test pack-------------------
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                dbToDMClassImporter.Import(null, GetDBTable());
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("dmSolution", ex.ParamName);
            }
        }


        [Test]
        public void Test_Import_WhenSolutionDefaultAssemblyIsNull_ShouldThrowError()
        {
            //---------------Set up test pack-------------------
            DMSolution solution = new DMSolution();
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNull(solution.DefaultAssembly);
            //---------------Execute Test ----------------------
            try
            {
                dbToDMClassImporter.Import(solution, GetDBTable());
                Assert.Fail("expected HabaneroDeveloperException");
            }
            //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains
                    ("You cannot create a DM Importer if the Solution does not have a default assembly", ex.Message);
            }
        }

        [Test]
        public void Test_TableNamePrefix_GetAndSet()
        {
            //---------------Set up test pack-------------------
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            string tableNamePrefix = TestUtilsShared.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            dbToDMClassImporter.TableNamePrefix = tableNamePrefix;
            //---------------Test Result -----------------------
            Assert.AreEqual(tableNamePrefix, dbToDMClassImporter.TableNamePrefix);

        }

        [Test]
        public void Test_PrimaryKeyColumnSuffix_GetAndSet()
        {
            //---------------Set up test pack-------------------
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            string primaryKeyColumnSuffix = TestUtilsShared.GetRandomString();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            dbToDMClassImporter.PrimaryKeyColumnSuffix = primaryKeyColumnSuffix;
            //---------------Test Result -----------------------
            Assert.AreEqual(primaryKeyColumnSuffix, dbToDMClassImporter.PrimaryKeyColumnSuffix);

        }

        [Test]
        public void Test_Import_WhenNullTable_ShouldThrowError()
        {
            //---------------Set up test pack-------------------
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            try
            {
                dbToDMClassImporter.Import(dmSolution, null);
                Assert.Fail("expected ArgumentNullException");
            }
            //---------------Test Result -----------------------
            catch (ArgumentNullException ex)
            {
                StringAssert.Contains("Value cannot be null", ex.Message);
                StringAssert.Contains("dbTable", ex.ParamName);
            }
        }

        [Test]
        public void Test_Import_NewTable_HasLeadingAndTrailingWhiteSpace()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable("  TableName  ");
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(dbTable.TableName.Trim(), dmClass.ClassNameBO);
            Assert.AreEqual(dbTable.TableID, dmClass.MappedTableID);
            Assert.AreEqual(dbTable.TableName, dmClass.MappedTableName);
            Assert.IsFalse(dmClass.Generated.Value, "business object should not be set as generated");
        }

        [Test]
        public void Test_Import_NewTable_HasWhiteSpaceInTableName()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable("  Table  Name  ");
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual("TableName", dmClass.ClassNameBO);
            Assert.AreEqual(dbTable.TableID, dmClass.MappedTableID);
            Assert.AreEqual(dbTable.TableName, dmClass.MappedTableName);
        }

        [Test]
        public void Test_Import_NewTable_ShouldAddToSolution()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable("TableName");
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmSolution.AllClasses.Count);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual(dbTable.TableName, dmClass.ClassNameBO);
            Assert.AreEqual(dbTable.TableID, dmClass.MappedTableID);
            Assert.AreEqual(1, dmSolution.AllClasses.Count);
        }
        [Test]
        public void Test_Import_NewTable_ShouldSetMappedTableNameAndMappedSchemaName()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable("TableName");
            var expectedSchemaName = GetRandomString();
            dbTable.SchemaName = expectedSchemaName;
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            //---------------Assert Precondition----------------
            Assert.IsNull(dbTable.GetMappedDMClass());
            Assert.IsNull(dmSolution.FindClassByMappedTableName(dbTable.TableName));
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass, "Mapped class has been created");
            Assert.AreEqual(expectedSchemaName, dmClass.MappedSchemaName);
        }
        [Test]
        public void Test_Import_MapedDMClassExists_ShouldUpdateMappedTableNameAndMappedSchemaName()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable("TableName");
            var expectedSchemaName = GetRandomString();
            dbTable.SchemaName = expectedSchemaName;
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            var dmClass = new DMClass {MappedDBTable = dbTable};
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dbTable.GetMappedDMClass());
            Assert.IsNullOrEmpty(dmClass.MappedSchemaName);
            //---------------Execute Test ----------------------
            DMClass importedDMClass  = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, importedDMClass, "Mapped class be origional mapped class");
            Assert.AreEqual(expectedSchemaName, importedDMClass.MappedSchemaName, "Schema name should have been updated");
        }

        [Test]
        public void Test_Import_ShouldConvertDBTableNameToClassName()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable("   TBLmy_table names ");
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            dbToDMClassImporter.TableNamePrefix = "tbl";
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual("MyTableName", dmClass.ClassNameBO);
        }

        [Test]
        public void Test_Import_ExistingMappedTable_WhenTableCommentUpdated_WhenClassDescriptionAlreadyExists_ShouldNotBeUpdated()
        {
            //Story: Future: This test could change to recognising that it can update because the comment wasn't edited since the last import
            //---------------Set up test pack-------------------
            const string tableName = "MappedTableName";
            const string origComments = "Orig Table Comment";
            const string newComment = "New Table Coments";
            IDBTable dbTable = GetTableWithPendingChangeTypeUpdated(tableName);
            dbTable.TableComment = origComments;
            DMAssembly dmAssembly;
            DMSolution dmSolution = GetDmSolutionWithDefaultAssembly(out dmAssembly);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            dbTable.TableComment = newComment;
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(origComments, dmClass.ClassDescription);
        }



        [Test]
        public void Test_ExistingMappedTable_WhenTableCommentUpdated_WhenClassDescriptionAlreadyEdited_ShouldNotBeUpdated()
        {
            //---------------Set up test pack-------------------
            const string tableName = "MappedTableName";
            const string origComments = "Orig Table Comment";
            const string updatedClassDesc = "Updated Class Description";
            const string newComment = "New Table Coments";
            IDBTable dbTable = GetTableWithPendingChangeTypeUpdated(tableName);
            dbTable.TableComment = origComments;
            DMAssembly dmAssembly;
            DMSolution dmSolution = GetDmSolutionWithDefaultAssembly(out dmAssembly);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            dmClass.ClassDescription = updatedClassDesc;
            dbTable.TableComment = newComment;
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(updatedClassDesc, dmClass.ClassDescription);
        }

        [Test]
        public void Test_Import_ExistingMappedTable_WhenTableCommentUpdated_WhenClassDescriptionEmpty_ShouldBeUpdated()
        {
            //---------------Set up test pack-------------------
            const string tableName = "MappedTableName";
            const string origComments = "Orig Table Comment";
            //const string updatedClassDesc = "Updated Class Description";
            const string newComment = "New Table Coments";
            IDBTable dbTable = GetTableWithPendingChangeTypeUpdated(tableName);
            dbTable.TableComment = origComments;
            DMAssembly dmAssembly;
            DMSolution dmSolution = GetDmSolutionWithDefaultAssembly(out dmAssembly);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            dmClass.ClassDescription = null;
            dbTable.TableComment = newComment;
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(newComment, dmClass.ClassDescription);
        }

        [Test]
        public void Test_ExistingTable_WhenNotMappedByTableID_ShouldFindExistingDMClass()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeUpdated(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(dbTable.TableName, dmClass.MappedTableName);
            Assert.AreEqual(ChangeType.Update, dbTable.PendingChangeType);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreEqual(1, dmAssembly.Classes.Count);

            Assert.IsNull(dmClass.MappedTable);
            Assert.IsNotNull(dmSolution.FindClassByMappedTableName(dbTable.TableName));
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreSame(dbTable, dmClass.MappedDBTable);
            Assert.AreEqual(1, dmAssembly.Classes.Count);
        }  

        [Test]
        public void Test_ExistingTable_WhenNotMappedByTableID_WhenFindExistingDMClass_ShouldUpdatedMappedSchemaName()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeUpdated(tableName);
            var expectedSchemaName = GetRandomString();
            dbTable.SchemaName = expectedSchemaName;
            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmClass.MappedTableID);
            Assert.IsNull(dbTable.GetMappedDMClass());
            Assert.IsNotNull(dmSolution.FindClassByMappedTableName(dbTable.TableName));

            Assert.IsNullOrEmpty(dmClass.MappedSchemaName);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(expectedSchemaName, returnedDMClass.MappedSchemaName);
        }
          
        [Test]
        public void Test_AddedTable_ExistingDMClass_MappedByTableName()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeAdd(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();

            //---------------Assert Precondition----------------
            Assert.AreEqual(ChangeType.Add, dbTable.PendingChangeType);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreEqual(1, dmAssembly.Classes.Count);
            Assert.AreEqual(tableName, dmClass.MappedTableName);
            Assert.IsNull(dmClass.MappedTableID);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableID, returnedDMClass.MappedTableID);
            Assert.AreEqual(1, dmAssembly.Classes.Count, "Did not create a new class");
        }

        //	If the DMClass Description == null then Update with the Table Description.
        [Test]
        public void Test_AddedTable_ExistingDMClass_MappedByTableName_DMClassHasNotDescription()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeAdd(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            dbTable.TableComment = "This is a comment";

            //---------------Assert Precondition----------------
            Assert.IsTrue(string.IsNullOrEmpty(dmClass.ClassDescription), dmClass.ClassDescription);
            Assert.IsFalse(string.IsNullOrEmpty(dbTable.TableComment));
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableComment, dmClass.ClassDescription);
        }

        [Test]
        public void Test_AddedTable_ExistingDMClass_MappedByTableName_DMClassHasDescription()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeAdd(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            dbTable.TableComment = "This is a comment";
            const string origDescription = "Has a description";
            dmClass.ClassDescription = origDescription;
            //---------------Assert Precondition----------------
            Assert.AreEqual(origDescription, dmClass.ClassDescription);
            Assert.IsFalse(string.IsNullOrEmpty(dbTable.TableComment));
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(origDescription, dmClass.ClassDescription);
        }

        [Test]
        public void Test_AddedTable_ExistingDMClass_NotMappedByTableName()
        {
            //---------------Set up test pack-------------------

            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeAdd(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass("Not Mapped TableName", out dmAssembly, out dmClass);

            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();

            //---------------Assert Precondition----------------
            Assert.AreEqual(ChangeType.Add, dbTable.PendingChangeType);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.AreEqual(1, dmAssembly.Classes.Count);
            Assert.AreNotEqual(tableName, dmClass.MappedTableName);
            Assert.IsNull(dmClass.MappedTableID);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreNotSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableID, returnedDMClass.MappedTableID);
            Assert.AreEqual(2, dmAssembly.Classes.Count, "Created a new class since no matching class found");
        }

        //the DMClass is mapped to another Table then do nothing.
        [Test]
        public void Test_AddedTable_ExistingDMClass_IsMappedToAnotherTable_DoNothing()
        {
            //---------------Set up test pack-------------------
            const string tableName = "MappedTableName";
            IDBTable dbTable = GetTableWithPendingChangeTypeAdd(tableName);

            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(tableName, out dmAssembly, out dmClass);
            dmClass.MappedTableID = Guid.NewGuid();
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(dmClass.MappedTableID, dbTable.TableID);
            Assert.AreEqual(dmClass.MappedTableName, dbTable.TableName);
            Assert.AreEqual(ChangeType.Add, dbTable.PendingChangeType);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreNotSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableID, returnedDMClass.MappedTableID);
            Assert.AreNotEqual(dbTable.TableID, dmClass.MappedTableID);
            Assert.AreEqual
                (2, dmAssembly.Classes.Count,
                 "Created a new class since matching class found was already associated with another DBTable");
        }

        [Test]
        public void Test_EditedTable_Renamed_WithExistingDMClass_WhenMappedByTableID_ShouldUpdateClass_ExceptClassName()
        {
            //---------------Set up test pack-------------------
            const string oldTableName = "OldTableName";
            const string newTableName = "New Table Name";
            const string newClassName = "NewTableName";
            IDBTable dbTable = GetDBTable(oldTableName);
            dbTable.Database = TestUtilsDBDatabase.CreateSavedDBDatabase();
            dbTable.Save();
            dbTable.TableName = newTableName;
            dbTable.PendingChangeType = ChangeType.Rename;
            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(oldTableName, out dmAssembly, out dmClass);
            dmClass.ClassNameBO = oldTableName;
            dmClass.MappedTableID = dbTable.TableID;
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(oldTableName, dmClass.MappedTableName);
            Assert.AreEqual(oldTableName, dmClass.ClassNameBO);
            Assert.AreEqual(newTableName, dbTable.TableName);
            Assert.AreNotEqual(oldTableName, dbTable.TableName);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableName, dmClass.MappedTableName);
            Assert.AreEqual(oldTableName, dmClass.ClassNameBO);
        }

        [Test]
        public void Test_Import_ShouldSetGetMappedTable()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable();
            DMSolution dmSolution = CreateDMSolution();
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreEqual(dbTable, returnedDMClass.MappedDBTable);
            Assert.AreEqual(returnedDMClass, dbTable.GetMappedDMClass());
        }

        [Test]
        public void Test_Import_D_ShouldSetGetMappedTable()
        {
            //---------------Set up test pack-------------------
            IDBTable dbTable = GetDBTable();
            DMSolution dmSolution = CreateDMSolution();
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreEqual(dbTable, returnedDMClass.MappedDBTable);
            Assert.AreEqual(returnedDMClass, dbTable.GetMappedDMClass());
        }


        [Test]
        public void Test_EditedTable_Renamed_WithExistingDMClass_WhenMappedByTableID_AndCustomClassName_ShouldUpdateClass_ExceptClassName()
        {
            //---------------Set up test pack-------------------
            const string oldTableName = "MappedTableName";
            const string newTableName = "New Table Name";
            const string customClassName = "CustomName";
            IDBTable dbTable = GetDBTable(oldTableName);
            dbTable.Database = TestUtilsDBDatabase.CreateSavedDBDatabase();
            dbTable.Save();
            dbTable.TableName = newTableName;
            dbTable.PendingChangeType = ChangeType.Rename;
            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(oldTableName, out dmAssembly, out dmClass);
            dmClass.ClassNameBO = customClassName;
            dmClass.MappedTableID = dbTable.TableID;
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(oldTableName, dmClass.MappedTableName);
            Assert.AreEqual(customClassName, dmClass.ClassNameBO);
            Assert.AreEqual(newTableName, dbTable.TableName);
            Assert.AreNotEqual(oldTableName, dbTable.TableName);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableName, dmClass.MappedTableName);
            Assert.AreEqual(customClassName, dmClass.ClassNameBO);
        }

        [Test]
        public void Test_EditedTable_Renamed_WithExistingDMClass_WhenMappedByTableID_AndClassNameCaseChanged_ShouldUpdateClass_ExceptClassName()
        {
            //---------------Set up test pack-------------------
            const string oldTableName = "MappedTableName";
            const string newTableName = "New Table Name";
            const string customCaseClassName = "CustomClassName";
            IDBTable dbTable = GetDBTable(oldTableName);
            dbTable.Database = TestUtilsDBDatabase.CreateSavedDBDatabase();
            dbTable.Save();
            dbTable.TableName = newTableName;
            dbTable.PendingChangeType = ChangeType.Rename;
            DMAssembly dmAssembly;
            DMClass dmClass;
            DMSolution dmSolution = GetSolutionWithOneClass(oldTableName, out dmAssembly, out dmClass);
            dmClass.ClassNameBO = customCaseClassName;
            dmClass.MappedTableID = dbTable.TableID;
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.AreEqual(oldTableName, dmClass.MappedTableName);
            Assert.AreEqual(customCaseClassName, dmClass.ClassNameBO);
            Assert.AreEqual(newTableName, dbTable.TableName);
            Assert.AreNotEqual(oldTableName, dbTable.TableName);
            //---------------Execute Test ----------------------
            DMClass returnedDMClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(dmClass, returnedDMClass);
            Assert.AreEqual(dbTable.TableName, dmClass.MappedTableName);
            Assert.AreEqual(customCaseClassName, dmClass.ClassNameBO);
        }


        protected virtual IDBTable GetDBTable(string tableName)
        {
            return new DBView(tableName);
        }

        protected virtual IDBTable GetDBTable()
        {
            return GetDBTable(GetRandomString());
        }

        private string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }

        private IDBTable GetTableWithPendingChangeTypeAdd(string tableName)
        {
            IDBTable dbTable = GetDBTable(tableName);

            dbTable.PendingChangeType = ChangeType.Add;
            return dbTable;
        }

        private IDBTable GetTableWithPendingChangeTypeUpdated(string tableName)
        {
            IDBTable dbTable = GetDBTable(tableName);
            dbTable.PendingChangeType = ChangeType.Update;
            return dbTable;
        }

        private static DMSolution GetSolutionWithOneClass
            (string tableName, out DMAssembly dmAssembly, out DMClass dmClass)
        {
            DMSolution dmSolution = GetDmSolutionWithDefaultAssembly(out dmAssembly);
            dmClass = new DMClass { MappedTableName = tableName, ClassNameBO = "MyClassName" };
            dmAssembly.Classes.Add(dmClass);
            return dmSolution;
        }

        private static DMSolution GetDmSolutionWithDefaultAssembly(out DMAssembly dmAssembly)
        {
            DMSolution dmSolution = new DMSolution();
            dmAssembly = new DMAssembly("AssemblyName");
            dmSolution.Assemblies.Add(dmAssembly);
            dmSolution.DefaultAssembly = dmAssembly;
            return dmSolution;
        }

        protected DMSolution CreateDMSolution()
        {
            return new DMSolution { DefaultAssembly = new DMAssembly("SomeAssemblyName") };
        }
    }

    [TestFixture]
    public class TestDBToDMClassImporter : TestDBToDMClassImporterBase
    {


        protected override IDBTable GetDBTable(string tableName)
        {
            return new DBTable(tableName);
        }
        //TODO: need to modify so that has relationship to the 
        // database field ID.
        // Then need to modify logic for creating setting databaseFieldName 
        // so that either from Prop name if id not set else from ID prop name
        // if prop name not set.
        [Test]
        public void Test_Import_ShouldConvertUsePKColumnNameToImproveClassName()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = (DBTable)GetDBTable("mytablename");
            DBTableBuilder tableBuilder = new DBTableBuilder(dbTable);
            tableBuilder.AddPrimaryKeyColumn("MyTableNameID");
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            DMSolution dmSolution = CreateDMSolution();
            dbToDMClassImporter.TableNamePrefix = "tbl";
            dbToDMClassImporter.PrimaryKeyColumnSuffix = "ID";
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass);
            Assert.AreEqual("MyTableName", dmClass.ClassNameBO);
        }
        [Test]
        public void Test_ShouldSetProjectAssemblyNameOnClass()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = CreateTableInfoWithSimplePrimaryKey("tableName", "TableNaMe");
            DMSolution dmSolution = new DMSolution {DefaultAssembly = new DMAssembly("AssemblyName")};
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmSolution.DefaultAssembly);
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.IsNotNull(dmClass);
            Assert.AreSame(dmSolution.DefaultAssembly, dmClass.Assembly);
        }
        [Test]
        public void Test_WhenNoDefaultAssembly_AndNoAssembliesOnSolution_ShouldRaiseException()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = CreateTableInfoWithSimplePrimaryKey("tableName", "TableNaMe");
            DMSolution dmSolution = new DMSolution();
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(0, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            try
            {
                DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
                Assert.Fail("expected HabaneroDeveloperException");
            }
                //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains("the Solution does not have a default assembly", ex.Message);
            }
        }

        [Test]
        public void Test_WhenNoDefaultAssembly_ButHasAssembliesOnSolution_ShouldCreateAssembly_ShouldSetProjectAssemblyNameOnClass()
        {

            //---------------Set up test pack-------------------
            DBTable dbTable = CreateTableInfoWithSimplePrimaryKey("tableName", "TableNaMe");
            DMSolution dmSolution = new DMSolution();
            var expectedDefaultAssembly = new DMAssembly("AssemblyName");
            dmSolution.Assemblies.Add(expectedDefaultAssembly);
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmSolution.DefaultAssembly);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreSame(expectedDefaultAssembly, dmSolution.DefaultAssembly);
            Assert.AreSame(expectedDefaultAssembly, dmClass.Assembly);
        }
        [Test]
        public void Test_TableCommentCopiedToBusinessObject()
        {
            //---------------Set up test pack-------------------
            DBTable dbTable = CreateTableInfoWithSimplePrimaryKey("tableName", "TableNaMe");
            DMSolution dmSolution = new DMSolution {DefaultAssembly = new DMAssembly("AssemblyName")};
            DBToDMClassImporter dbToDMClassImporter = new DBToDMClassImporter();
            const string tableComment = "This is what this table is for";
            dbTable.TableComment = tableComment;
            //---------------Assert Precondition----------------
            Assert.AreEqual(tableComment, dbTable.TableComment);
            //---------------Execute Test ----------------------
            DMClass dmClass = dbToDMClassImporter.Import(dmSolution, dbTable);
            //---------------Test Result -----------------------
            Assert.AreEqual(tableComment, dmClass.ClassDescription);
        }
/*
        private string GetRandomString()
        {
            return RandomValueGen.GetRandomString();
        }*/



        private  DBTable CreateTableInfoWithSimplePrimaryKey(string tableName, string columnName)
        {
            DBTable dbTable = (DBTable)GetDBTable(tableName);
            DBColumn dbColumn = dbTable.Columns.CreateBusinessObject();
            dbColumn.ColumnName = columnName;
            dbTable.PrimaryKeyDB = new DBPrimaryKey();
            dbTable.PrimaryKeyDB.AddColumnInfo(dbColumn);
            return dbTable;
        }
    }

    
}